package com.pic.mgt.syushin.action;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.pic.mgt.SyushinLauncher;
import com.pic.mgt.log.IgxLog;
import com.pic.mgt.manager.business.BasicBusinessInfoBean;
import com.pic.mgt.scheduler.SchedulerException;
import com.pic.mgt.syushin.SyushinScheduler;
import com.pic.mgt.syushin.executer.bucket.SimpleSyushinBucketProcess;
import com.pic.mgt.syushin.executer.bucket.SyushinBucketExecutionQuartzJobBean;
import com.pic.mgt.syushin.manager.business.SyushinBusinessManager;

public class SyushinPackageScheduleMgtActionImpl implements
		SyushinPackageScheduleMgtAction {
	
	private SyushinScheduler syushinScheduler;
	private SyushinBusinessManager syushinBusinessManager;

	@Override
	public boolean addSchedule(String businessName, String scheduleName,
			String scheduleDescrption, String cronExpression) {
		if (null == businessName || businessName.isEmpty() ||
			null == scheduleName || scheduleName.isEmpty() ||
			null == cronExpression || cronExpression.isEmpty()) {
			// ********************** Log **********************
			IgxLog.messageLog.warn(this,
							"Adding packaging schedule failed. Did not provide business name, schedule name or cron expression.");
			// ********************** Log **********************
			
			return false;
		}
		
		// 先檢查是否有此業務
		boolean isEffectiveBusiness =
			this.syushinBusinessManager.isEffectiveBusiness(businessName);
		if (!isEffectiveBusiness) {
			// ********************** Log **********************
			IgxLog.messageLog.warn(this,
							"Adding syushin business '{}' packaging schedule failed. Because of no such business.",
							businessName);
			// ********************** Log **********************
			
			return false;
		}
		
		// Job Data
		Map<String,String> jobData = new HashMap<String,String>();
		jobData.put(SyushinScheduler.JOB_DATA_BUSINESS_NNAME_KEY, businessName);
		
		try {
			this.syushinScheduler.scheduleCronJob(cronExpression,
												  scheduleName,
												  getBizPackagingScheduleGroupName(businessName),
												  scheduleDescrption,
												  SyushinBucketExecutionQuartzJobBean.class,
												  jobData);
		} catch (SchedulerException e) {
			// 不用寫 log
			return false;
		}
		
		// ********************** Log **********************
		IgxLog.messageLog.info(this,
						"Adding syushin business '{}' packaging schedule (cron expression:'{}') completed. (schedule name:'{}'",
						businessName, cronExpression, scheduleName);
		// ********************** Log **********************
		
		return true;
	}

	@Override
	public boolean modifySchedule(String businessName, String scheduleName,
			String scheduleDescrption, String cronExpression) {
		if (null == scheduleName || scheduleName.isEmpty() ||
			null == cronExpression || cronExpression.isEmpty() ||
			null == businessName || businessName.isEmpty()) {
					// ********************** Log **********************
					IgxLog.messageLog.warn(this,
									"Modifying business list synchronization schedule failed. Did not provide business name, schedule name or cron expression.");
					// ********************** Log **********************
					
					return false;
		}
		
		
		String groupName = getBizPackagingScheduleGroupName(businessName);
		
		try {
			this.syushinScheduler.rescheduleCronJob(cronExpression, scheduleName, groupName, scheduleDescrption);
		} catch (SchedulerException e) {
			// 不用寫 log
			return false;
		}
		
		// ********************** Log **********************
		IgxLog.messageLog.info(this,
						"Modifying syushin business '{}' packaging schedule (with cron expression:'{}') completed. (schedule name:'{}'",
						businessName, cronExpression, scheduleName);
		// ********************** Log **********************
		
		return true;
	}
	
	@Override
	public boolean removeSchedule(String businessName, String scheduleName) {
		if (null == businessName || businessName.isEmpty() ||
			null == scheduleName || scheduleName.isEmpty()) {
			// ********************** Log **********************
			IgxLog.messageLog.warn(this,
							"Removing syushin business packaging schedule failed. Did not provide business name or schedule name.");
			// ********************** Log **********************
			
			return false;
		}
		
		
		try {
			this.syushinScheduler.removeJob(scheduleName,
											getBizPackagingScheduleGroupName(businessName));
		} catch (SchedulerException e) {
			// 不用寫 log
			return false;
		}
		
		// ********************** Log **********************
		IgxLog.messageLog.info(this,
						"Removing syushin business '{}' packaging schedule completed. (schedule name:'{}')",
						businessName, scheduleName);
		// ********************** Log **********************
		
		return true;
	}
	
	@Override
	public boolean pausePackagingSchedule() {
		List<BasicBusinessInfoBean> basicBusinessInfoBeanList =
					this.syushinBusinessManager.getEffectiveBasicBusinessInfoBeanList();
		for (BasicBusinessInfoBean basicBusinessInfoBean : basicBusinessInfoBeanList) {
			boolean isPausePackagingScheduleSuccessful = 
					pausePackagingSchedule(basicBusinessInfoBean.getBusinessName());
			if (!isPausePackagingScheduleSuccessful) {
				return false;
			}
		}
		
		return true;
	}
	
	@Override
	public boolean resumePackagingSchedule() {
		List<BasicBusinessInfoBean> basicBusinessInfoBeanList =
			this.syushinBusinessManager.getEffectiveBasicBusinessInfoBeanList();
		for (BasicBusinessInfoBean basicBusinessInfoBean : basicBusinessInfoBeanList) {
			boolean isResumePackagingScheduleSuccessful = 
					resumePackagingSchedule(basicBusinessInfoBean.getBusinessName());
			if (!isResumePackagingScheduleSuccessful) {
				return false;
			}
		}
		
		return true;
	}
	
	@Override
	public boolean pausePackagingSchedule(String businessName) {
		try {
			String packagingBusinessScheduleGroupName = getBizPackagingScheduleGroupName(businessName);
			this.syushinScheduler.pauseJobGroup(packagingBusinessScheduleGroupName);
		} catch (SchedulerException e) {
			// 不用寫 log
			return false;
		}
		
		// ********************** Log **********************
		IgxLog.messageLog.info(this,
						"Pausing syushin business '{}' packaging schedule completed.",
						businessName);
		// ********************** Log **********************
		
		return true;
	}
	
	@Override
	public boolean resumePackagingSchedule(String businessName) {
		try {
			String packagingBusinessScheduleGroupName = getBizPackagingScheduleGroupName(businessName);
			this.syushinScheduler.resumeJobGroup(packagingBusinessScheduleGroupName);
		} catch (SchedulerException e) {
			// 不用寫 log
			return false;
		}
		
		// ********************** Log **********************
		IgxLog.messageLog.info(this,
						"Resuming syushin business '{}' packaging schedule completed.",
						businessName);
		// ********************** Log **********************
		
		return true;
	}
	
	@Override
	public String getPackagingScheduleInfoByBizName(String businessName) {
		String groupName = getBizPackagingScheduleGroupName(businessName);
		try {
			// throws SchedulerException
			List<Map<String, Object>> jobInfoMapList =
				this.syushinScheduler.getScheduleJobInfoByGroupName(groupName);
			
			return this.syushinScheduler.formatSchedules(jobInfoMapList);
		} catch (SchedulerException e) {
			// 不用寫 log (已寫)
			return null;
		}
	}
	
	@Override
	public boolean packagingBusiness(String businessName) {
		if (null == businessName || businessName.isEmpty()) {
			// ********************** Log **********************
			IgxLog.messageLog.warn(this,
							"Packaging business failed. Did not provide business name.");
			// ********************** Log **********************
			
			return false;
		}
		
		// 先檢查是否有此業務
		boolean isEffectiveBusiness =
			this.syushinBusinessManager.isEffectiveBusiness(businessName);
		if (!isEffectiveBusiness) {
			// ********************** Log **********************
			IgxLog.messageLog.error(this,
							"SUDA-291 Packaging syushin business '{}' failed. Because of no such business.",
							businessName);
			// ********************** Log **********************
			
			return false;
		}
		
		SimpleSyushinBucketProcess syushinBucketProcess = 
							SyushinLauncher.applicationContext.getBean(
														"simpleSyushinBucketProcess",
														SimpleSyushinBucketProcess.class);
		syushinBucketProcess.perform(businessName);
		
		return true;
	}
	
	/**
	 * 取得業務的打包排程群組(Group)名稱
	 * @param businessName
	 * @return
	 */
	public static String getBizPackagingScheduleGroupName(String businessName) {
		return
			businessName + SyushinScheduler.BUCKET_JOB_GROUP_NAME_SUFFIX;
	}
	
	// --- getter and setter ---

	public void setSyushinScheduler(SyushinScheduler syushinScheduler) {
		this.syushinScheduler = syushinScheduler;
	}

	public void setSyushinBusinessManager(
			SyushinBusinessManager syushinBusinessManager) {
		this.syushinBusinessManager = syushinBusinessManager;
	}

}
